#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "../include/queue.h"

struct queueCDT
{
	struct nodoCDT* nodos;
	int tam;
};

typedef struct nodoCDT
{
	void * dato;    /* donde se guarda la informaci�n */
	struct nodoCDT* tail;
} nodoCDT;


static void
Error(const char* cartel)
{
	fprintf(stderr, "%s", cartel);
	exit(1);
}

queueADT
openPQueue(int tam){

	queueADT auxi;

	if ( (auxi= malloc(sizeof( struct queueCDT)) )== NULL )
		Error("No hay lugar disponible\n");

	auxi->nodos= NULL;
	auxi->tam= tam;
	return auxi;
}

int
isEmpty(queueADT queue){
	return queue->nodos == NULL;
}

//busca el primer elemento pero no lo saca de la cola
void *
checkFirst(queueADT queue){
	if (queue->nodos == NULL)
		return NULL;

	return queue->nodos->dato;

}

static nodoCDT*
listTail ( nodoCDT* listInterna )
{
	if ( listInterna == NULL )
		Error("Acceso a la cola de una lista vacia\n");
	return listInterna->tail;
}


//agrega un elemento
void
addElem(queueADT queue, void * element){
	nodoCDT *ant, *rec, *auxi;

	ant= rec= queue->nodos;
	while( rec != NULL )
	{
		ant= rec;
		rec= listTail( rec );
	}
	if ( (auxi= malloc( sizeof (nodoCDT) )) == NULL )
		Error("No hay lugar\n");

	auxi->tail= rec;

	/* genero lugar para copiar la informacion que
	   recibo indirectamente */
	if ( (auxi->dato= malloc(queue->tam)) == NULL)
	{
	    free(auxi);
	    Error("No hay lugar para otro nodo\n");
	}


	memcpy(auxi->dato, element, queue->tam);

	if ( ant == rec ) /* es el primero */
		queue->nodos= auxi;
	else
		ant->tail= auxi;

}

//busca y saca el primer elemento de la cola
//el usuario debe hacer free del elemento cuando deje de usarlo
void *
getElem(queueADT queue){
	void * dato;
	if (queue->nodos == NULL)
		return NULL;

	nodoCDT * aux = queue->nodos;
	queue->nodos = aux->tail;

	if ( (dato = malloc(queue->tam)) == NULL )
		return NULL;

	memcpy(dato, aux->dato, queue->tam);

	free(aux->dato);
	free(aux);

	return dato;
}

void
freePQueue(queueADT queue){

	nodoCDT* auxi;
	while ( ! isEmpty( queue ) )
	{
		auxi= queue->nodos;
		queue->nodos= auxi->tail;
		free(auxi->dato);
		free(auxi);
	}
	free(queue);
}

